package com.baidu.encrypt.service.impl;


import com.baidu.encrypt.common.utils.SM3Util;
import com.baidu.encrypt.common.utils.SM4Util;
import com.baidu.encrypt.entity.BusinessAppInfo;
import com.baidu.encrypt.entity.CustomModel;
import com.baidu.encrypt.entity.KnowledgeFileInfo;
import com.baidu.encrypt.entity.KnowledgeFileInfo;
import com.baidu.encrypt.mapper.BusinessAppInfoMapper;
import com.baidu.encrypt.mapper.KnowledgeFileInfoMapper;
import com.baidu.encrypt.service.BusinessAppInfoService;
import com.baidu.encrypt.service.KnowledgeFileInfoService;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.Date;
import java.util.StringJoiner;

@Service
public class KnowledgeFileInfoServiceImpl extends ServiceImpl<KnowledgeFileInfoMapper, KnowledgeFileInfo> implements KnowledgeFileInfoService {
    @Autowired
    private SM4Util sm4Util;

    @Override
    public <E extends IPage<KnowledgeFileInfo>> E page(E page, Wrapper<KnowledgeFileInfo> queryWrapper) {
        E result = super.page(page, queryWrapper);
        result.getRecords().forEach(this::decryptEntity); // 只解密，不做篡改校验
        return result;
    }


    @Override
    public boolean save(KnowledgeFileInfo entity) {
        encryptEntity(entity);
        return super.save(entity);
    }

    @Override
    public boolean updateById(KnowledgeFileInfo entity) {

        //        String userId = UserContext.getUserId();
        String userId = "xiaofei";
        if (userId != null) {
            entity.setUpdatedBy(userId);
        }
        entity.setUpdatedTime(new Date());

        KnowledgeFileInfo byId = getById(entity.getId());
        byId.setCreatedBy(entity.getCreatedBy() == null ? byId.getCreatedBy() : entity.getCreatedBy());
        byId.setUpdatedBy(entity.getUpdatedBy() == null ? byId.getUpdatedBy() : entity.getUpdatedBy());
        byId.setName(entity.getName() == null ? byId.getName() : entity.getName());
        byId.setSource(entity.getSource() == null ? byId.getSource() : entity.getSource());
        byId.setTags(entity.getTags() == null ? byId.getTags() : entity.getTags());
        byId.setVersion(entity.getVersion() == null ? byId.getVersion() : entity.getVersion());
        byId.setStoragePath(entity.getStoragePath() == null ? byId.getStoragePath() : entity.getStoragePath());
        byId.setFileName(entity.getFileName() == null ? byId.getFileName() : entity.getFileName());
        byId.setFileSize(entity.getFileSize() == null ? byId.getFileSize() : entity.getFileSize());
        byId.setFileType(entity.getFileType() == null ? byId.getFileType() : entity.getFileType());
        byId.setProjectId(entity.getProjectId() == null ? byId.getProjectId() : entity.getProjectId());

        encryptEntity(byId);
        return super.updateById(byId);
    }

    @Override
    public KnowledgeFileInfo getById(Serializable id) {
        KnowledgeFileInfo entity = super.getById(id);
        if (entity != null) {
            decryptEntity(entity);
            verifyIntegrity(entity);
        }
        return entity;
    }

    /** 加密（存库前） */
    private void encryptEntity(KnowledgeFileInfo knowledgeFileInfo) {
        try {
            // 先用明文计算 SM3
            String sm3Plain = buildPlainString(knowledgeFileInfo);
            knowledgeFileInfo.setSm3(SM3Util.encrypt(sm3Plain));

            // 对每个字段加密（空值不加密，直接存 null）
            knowledgeFileInfo.setName(encryptNullable(knowledgeFileInfo.getName()));
            knowledgeFileInfo.setSource(encryptNullable(knowledgeFileInfo.getSource()));
            knowledgeFileInfo.setTags(encryptNullable(knowledgeFileInfo.getTags()));
            knowledgeFileInfo.setVersion(encryptNullable(knowledgeFileInfo.getVersion()));
            knowledgeFileInfo.setStoragePath(encryptNullable(knowledgeFileInfo.getStoragePath()));
            knowledgeFileInfo.setFileName(encryptNullable(knowledgeFileInfo.getFileName()));
            knowledgeFileInfo.setFileSize(encryptNullable(knowledgeFileInfo.getFileSize()));
            knowledgeFileInfo.setFileType(encryptNullable(knowledgeFileInfo.getFileType()));
            knowledgeFileInfo.setCreatedBy(encryptNullable(knowledgeFileInfo.getCreatedBy()));
            knowledgeFileInfo.setUpdatedBy(encryptNullable(knowledgeFileInfo.getUpdatedBy()));
            knowledgeFileInfo.setProjectId(encryptNullable(knowledgeFileInfo.getProjectId()));
        } catch (Exception e) {
            throw new RuntimeException("加密失败", e);
        }
    }

    /** 解密（查库后） */
    private void decryptEntity(KnowledgeFileInfo knowledgeFileInfo) {
        try {
            knowledgeFileInfo.setName(decryptNullable(knowledgeFileInfo.getName()));
            knowledgeFileInfo.setSource(decryptNullable(knowledgeFileInfo.getSource()));
            knowledgeFileInfo.setTags(decryptNullable(knowledgeFileInfo.getTags()));
            knowledgeFileInfo.setVersion(decryptNullable(knowledgeFileInfo.getVersion()));
            knowledgeFileInfo.setStoragePath(decryptNullable(knowledgeFileInfo.getStoragePath()));
            knowledgeFileInfo.setFileName(decryptNullable(knowledgeFileInfo.getFileName()));
            knowledgeFileInfo.setFileSize(decryptNullable(knowledgeFileInfo.getFileSize()));
            knowledgeFileInfo.setFileType(decryptNullable(knowledgeFileInfo.getFileType()));
            knowledgeFileInfo.setCreatedBy(decryptNullable(knowledgeFileInfo.getCreatedBy()));
            knowledgeFileInfo.setUpdatedBy(decryptNullable(knowledgeFileInfo.getUpdatedBy()));
            knowledgeFileInfo.setProjectId(decryptNullable(knowledgeFileInfo.getProjectId()));
        } catch (Exception e) {
            throw new RuntimeException("解密失败", e);
        }
    }

    /** 防篡改校验 */
    private void verifyIntegrity(KnowledgeFileInfo knowledgeFileInfo) {
        String sm3New = SM3Util.encrypt(buildPlainString(knowledgeFileInfo));
        if (!sm3New.equals(knowledgeFileInfo.getSm3())) {
            throw new SecurityException("数据已被篡改！");
        }
    }

    /** 构建明文串（SM3用，null 统一转 ""） */
    private String buildPlainString(KnowledgeFileInfo s) {
        return new StringJoiner("|")
                .add(nullToEmpty(s.getName()))
                .add(nullToEmpty(s.getSource()))
                .add(nullToEmpty(s.getTags()))
                .add(nullToEmpty(s.getVersion()))
                .add(nullToEmpty(s.getStoragePath()))
                .add(nullToEmpty(s.getFileName()))
                .add(nullToEmpty(s.getFileSize()))
                .add(nullToEmpty(s.getFileType()))
                .add(nullToEmpty(s.getCreatedBy()))
                .add(nullToEmpty(s.getUpdatedBy()))
                .add(nullToEmpty(s.getProjectId()))
                .toString();
    }

    /** 工具方法：null → "" */
    private String nullToEmpty(String str) {
        return str == null ? "" : str;
    }

    /** 工具方法：加密 null 安全 */
    private String encryptNullable(String value) throws Exception {
        return value == null ? null : sm4Util.encrypt(value);
    }

    /** 工具方法：解密 null 安全 */
    private String decryptNullable(String value) throws Exception {
        return value == null ? null : sm4Util.decrypt(value);
    }
}
